﻿package com.moke.util.effect
{

	import flash.display.BitmapData;
	import flash.display.BitmapDataChannel;
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.filters.DisplacementMapFilter;
	import flash.filters.DisplacementMapFilterMode;
	import flash.geom.Point;
	import flash.utils.Timer;			

	/**
	 * ...
	 * 轻松产生水波效果，并有丰富的参数控制水波的各个属性
	 * 注意构造函数后要执行start()函数开始模拟
	 * @author moke
	 * 
	 * [Embed(source = 'pics/pic1.jpg')]
	   private var pic:Class;
	   private var image:Bitmap = new pic() as Bitmap;
			
	   public function SimpleTest() 
		{
			addChild(image);
			var effect:NoiseEffect = new NoiseEffect(image, new Point(), image.width+20, image.height+20);
			effect.start();			
		}
	 */
	public class NoiseEffect
	{
		private var _target:DisplayObject;
		private var _timer:Timer;
		private var _offset:Point = new Point();
		private var _offsetAdder:Point = new Point(2, 2);
		private var _bmd:BitmapData;
		private var _sv:int = 100;
		private var _sh:int = 100;
		private var _mapPoint:Point;
		private var _bmdWidth:int;
		private var _bmdHeight:int;
		private var _delay:Number = 1000 / 24;
		private var _mode:String = DisplacementMapFilterMode.COLOR;
		private var _bmdScaleX:Number = 20;
		private var _bmdScaleY:Number = 20;
		private var _numOctaves:int = 1;
		private var _randomSeed:int = 1;

		/**
		 *
		 * @param	target 目标
		 * @param	mapPoint 开始点
		 * @param	bmdWidth 想要模拟的宽度
		 * @param	bmdHeight 想要模拟的高度
		 */
		public function NoiseEffect(target:DisplayObject, mapPoint:Point, bmdWidth:int, bmdHeight:int)
		{
			this._target = target;
			this._mapPoint = mapPoint;
			this._bmdWidth = bmdWidth;
			this._bmdHeight = bmdHeight;
			this._bmdWidth = Math.max(1, _bmdWidth);
			this._bmdHeight = Math.max(1, _bmdHeight);
			init();
		}

		private function init():void
		{
			_bmd = new BitmapData(_bmdWidth, _bmdHeight);
			_timer = new Timer(_delay);
			_timer.addEventListener(TimerEvent.TIMER, update);
		}

		/**
		 * 开始模拟
		 */
		public function start():void
		{
			_timer.start();
		}

		/**
		 * 暂停模拟
		 */
		public function pause():void
		{
			_timer.stop();
		}

		/**
		 * 停止模拟
		 */
		public function stop():void
		{
			_target.filters = [];
			_timer.stop();
		}

		/**
		 * 是否正在运行
		 * @return
		 */
		public function isRunning():Boolean
		{
			return _timer.running;
		}

		private function update(e:Event):void
		{
			_offset.x += _offsetAdder.x;
			_offset.y += _offsetAdder.y;
			_bmd.perlinNoise(_sv, _sh, _numOctaves, _randomSeed, true, false, 7, false, [_offset]);
			_target.filters = [new DisplacementMapFilter(_bmd, _mapPoint, BitmapDataChannel.RED, 
				BitmapDataChannel.BLUE, _bmdScaleX, _bmdScaleY, _mode)];
		}

		/**
		 * 每次偏移的x，y值
		 */
		public function set offsetAdder(value:Point):void
		{
			_offsetAdder = value;
		}

		/**
		 * 竖直方向的基本块大小
		 */
		public function set vGap(value:int):void
		{
			_sv = value;
		}

		/**
		 * 水平方向的基本块大小
		 */
		public function set hGap(value:int):void
		{
			_sh = value;
		}

		/**
		 * 设置模拟的起始点
		 */
		public function set mapPoint(value:Point):void
		{
			_mapPoint = value;
		}

		/**
		 * 设置延迟间隔
		 */
		public function set delay(value:Number):void
		{
			_delay = value;
			_timer.delay = delay;
		}

		/**
		 * 模拟的模式
		 */
		public function set mode(mode:String):void
		{
			this._mode = mode;
		}

		/**
		 * x方向的拉伸
		 */
		public function set bmdScaleX(value:Number):void
		{
			_bmdScaleX = value;
		}

		/**
		 * y方向的拉伸
		 */
		public function set bmdScaleY(value:Number):void
		{
			_bmdScaleY = value;
		}

		/**
		 * 偏移
		 */
		public function set offset(value:Point):void
		{
			_offset = value;
		}

		/**
		 *
		 * @param	width bmd宽度
		 * @param	height bmd高度
		 */
		public function setBmdWH(width:int, height:int):void
		{
			_bmd = new BitmapData(width, height);
		}

		/**
		 * 模拟的次数
		 */
		public function set numOctaves(value:int):void
		{
			_numOctaves = value;
		}

		/**
		 * 随机种子
		 */
		public function set randomSeed(value:int):void
		{
			_randomSeed = value;
		}


		public function get offsetAdder():Point
		{
			return _offsetAdder;
		}

		public function get vGap():int
		{
			return _sv;
		}

		public function get hGap():int
		{
			return _sh;
		}

		public function get mapPoint():Point
		{
			return _mapPoint;
		}

		public function get delay():Number
		{
			return _delay;
		}

		public function get mode():String
		{
			return this._mode;
		}

		public function get bmdScaleX():Number
		{
			return _bmdScaleX;
		}

		public function get bmdScaleY():Number
		{
			return _bmdScaleY;
		}

		public function get offset():Point
		{
			return _offset;
		}

		public function get bmdWidth():int
		{
			return _bmd.width;
		}

		public function get bmdHeight():int
		{
			return _bmd.height;
		}

		public function get numOctaves():int
		{
			return _numOctaves;
		}

		public function get randomSeed():int
		{
			return _randomSeed;
		}
	}

}
